import 'dart:convert';

import 'package:amap_map_fluttify/amap_map_fluttify.dart';
import 'package:detect/utils/connect_state_util.dart';
import 'package:detect/utils/option_util.dart';
import 'package:intl/intl.dart';
import 'package:network_info_plus/network_info_plus.dart';

abstract class Entity {
  Map<String, dynamic> toJson();

  @override
  String toString() => jsonEncode(this);
}

class NetworkStateEntity implements Entity {
  bool hasNetwork;
  bool isWifi;
  String? wifiName;

  NetworkStateEntity(this.hasNetwork, this.isWifi, this.wifiName);

  @override
  NetworkStateEntity.fromJson(Map<String, dynamic> json)
      : hasNetwork = json['hasNetwork'],
        isWifi = json['isWifi'],
        wifiName = json['wifiName'];

  @override
  Map<String, dynamic> toJson() => {'hasNetwork': hasNetwork, 'isWifi': isWifi, 'wifiName': wifiName};

  static Future<NetworkStateEntity> get get async {
    NetworkInfo networkInfo = NetworkInfo();
    return Future.value(NetworkStateEntity(await ConnectStateUtil.instance.hasNetwork, await ConnectStateUtil.instance.isWifi, await networkInfo.getWifiName()));
  }
}

class RadioEntity implements Entity {
  int id;
  String name;
  int type;
  int antenna;
  String lat;
  String lng;

  RadioEntity(this.id, this.name, this.type, this.antenna, this.lat, this.lng);

  RadioEntity.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        name = json['name'],
        type = json['type'],
        antenna = json['antenna'],
        lat = json['lat'],
        lng = json['lng'];

  @override
  Map<String, dynamic> toJson() => {
        'id': id,
        'name': name,
        'type': type,
        'antenna': antenna,
        'lat': lat,
        'lng': lng,
      };

  LatLng get latLng => LatLng(double.tryParse(lat) ?? 0, double.tryParse(lng) ?? 0);

  RadioType get radioType => RadioType.values[type];

  AntennaType get antennaType => AntennaType.values[antenna];
}

class DisabledMHzEntity implements Entity {
  int? id;
  String values;

  DisabledMHzEntity(this.values);

  DisabledMHzEntity.set({this.id, required this.values});

  DisabledMHzEntity.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        values = json['values'];

  @override
  Map<String, dynamic> toJson() => {
        'id': id,
        'values': values,
      };

  List<double> get mhz => values.split(",").where((e) => e.isNotEmpty).map((e) => double.parse(e)).toList();
}

class DetectTaskEntity implements Entity {
  int? id;
  int radioId;
  String? radioName;
  String type;
  String role;
  String name;
  String time;
  int disabledMHzId;
  String? disabledMHzValues;
  int state;

  DetectTaskEntity(this.radioId, this.type, this.role, this.name, this.time, this.disabledMHzId, this.state);

  DetectTaskEntity.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        radioId = json['radio_id'],
        radioName = json['radio_name'],
        type = json['type'],
        role = json['role'],
        name = json['name'],
        time = json['time'],
        disabledMHzId = json['disabled_mhz_id'],
        disabledMHzValues = json['disabled_mhz_values'],
        state = json['state'];

  @override
  Map<String, dynamic> toJson() => {
        'id': id,
        'radio_id': radioId,
        'type': type,
        'role': role,
        'name': name,
        'time': time,
        'disabled_mhz_id': disabledMHzId,
        'state': state,
      };

  bool get isDetect => state == 1;
}

class DetectTaskBestEntity implements Entity {
  int? id;
  String type;
  String name;
  int radioId;
  String? radioName;
  String? startTime;
  String? endTime;
  String time;
  String resultIds;

  DetectTaskBestEntity(this.type, this.name, this.radioId, this.startTime, this.endTime, this.time, this.resultIds);

  DetectTaskBestEntity.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        type = json['type'],
        name = json['name'],
        radioId = json['radio_id'],
        radioName = json['radio_name'],
        startTime = json['start_time'],
        endTime = json['end_time'],
        time = json['time'],
        resultIds = json['result_ids'];

  @override
  Map<String, dynamic> toJson() => {
        'id': id,
        'type': type,
        'name': name,
        'radio_id': radioId,
        'start_time': startTime,
        'end_time': endTime,
        'time': time,
        'result_ids': resultIds,
      };
}

class GeneralTaskHoursEntity implements Entity {
  int? id;
  int detectTaskId;
  int hour;
  int startHz;
  int endHz;
  int power;

  GeneralTaskHoursEntity(this.detectTaskId, this.hour, this.startHz, this.endHz, this.power);

  GeneralTaskHoursEntity.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        detectTaskId = json['detect_task_id'],
        hour = json['hour'],
        startHz = json['start_hz'],
        endHz = json['end_hz'],
        power = json['power'];

  @override
  Map<String, dynamic> toJson() => {
        'id': id,
        'detect_task_id': detectTaskId,
        'hour': hour,
        'start_hz': startHz,
        'end_hz': endHz,
        'power': power,
      };

  String get hours {
    String h = hour < 10 ? '0$hour' : hour.toString();
    return "$h:00:00-$h:59:59";
  }
}

class GeneralTaskResultEntity implements Entity {
  int? id;
  int detectTaskId;
  DetectTaskEntity? detectTask;
  String time;
  int channel;
  int hz;
  double signal;
  double noise;
  double doppler;
  double multiPath;

  GeneralTaskResultEntity(this.detectTaskId, this.time, this.channel, this.hz, this.signal, this.noise, this.doppler, this.multiPath);

  GeneralTaskResultEntity.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        detectTaskId = json['detect_task_id'],
        detectTask = DetectTaskEntity.fromJson(json),
        time = json['as_time'] ?? json['time'],
        channel = json['channel'],
        hz = json['hz'],
        signal = json['signal'],
        noise = json['noise'],
        doppler = json['doppler'],
        multiPath = json['multi_path'];

  @override
  Map<String, dynamic> toJson() => {
        'id': id,
        'detect_task_id': detectTaskId,
        'time': time,
        'channel': channel,
        'hz': hz,
        'signal': signal,
        'noise': noise,
        'doppler': doppler,
        'multi_path': multiPath,
      };

  String get hours {
    DateFormat dateFormat = DateFormat('yyyy-MM-dd HH:mm:ss');
    int hour = dateFormat.parse(time).hour;
    String h = hour < 10 ? '0$hour' : hour.toString();
    return "$h:00:00-$h:59:59";
  }
}

class PickTaskHoursEntity implements Entity {
  int? id;
  int detectTaskId;
  int hour;
  int power;
  String modemType;
  String strategy;
  String hzs;

  PickTaskHoursEntity(this.detectTaskId, this.hour, this.power, this.modemType, this.strategy, this.hzs);

  PickTaskHoursEntity.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        detectTaskId = json['detect_task_id'],
        hour = json['hour'],
        power = json['power'],
        modemType = json['modem_type'],
        strategy = json['strategy'],
        hzs = json['hzs'];

  @override
  Map<String, dynamic> toJson() => {
        'id': id,
        'detect_task_id': detectTaskId,
        'hour': hour,
        'power': power,
        'modem_type': modemType,
        'strategy': strategy,
        'hzs': hzs,
      };

  String get hours {
    String h = hour < 10 ? '0$hour' : hour.toString();
    return "$h:00:00-$h:59:59";
  }
}

class PickTaskResultEntity implements Entity {
  int? id;
  int detectTaskId;
  DetectTaskEntity? detectTask;
  String time;
  int hz;
  double syncC0;
  double lostC0;
  double syncC1;
  double lostC1;
  double syncC3;
  double lostC3;
  double snrLora;
  double snrC0;
  double snrC1;
  double snrC3;

  PickTaskResultEntity(this.detectTaskId, this.time, this.hz, this.syncC0, this.lostC0, this.syncC1, this.lostC1, this.syncC3, this.lostC3, this.snrLora, this.snrC0, this.snrC1, this.snrC3);

  PickTaskResultEntity.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        detectTaskId = json['detect_task_id'],
        detectTask = DetectTaskEntity.fromJson(json),
        time = json['as_time'] ?? json['time'],
        hz = json['hz'],
        syncC0 = json['sync_c0'],
        lostC0 = json['lost_c0'],
        syncC1 = json['sync_c1'],
        lostC1 = json['lost_c1'],
        syncC3 = json['sync_c3'],
        lostC3 = json['lost_c3'],
        snrLora = json['snr_lora'],
        snrC0 = json['snr_c0'],
        snrC1 = json['snr_c1'],
        snrC3 = json['snr_c3'];

  @override
  Map<String, dynamic> toJson() => {
        'id': id,
        'detect_task_id': detectTaskId,
        'time': time,
        'hz': hz,
        'sync_c0': syncC0,
        'lost_c0': lostC0,
        'sync_c1': syncC1,
        'lost_c1': lostC1,
        'sync_c3': syncC3,
        'lost_c3': lostC3,
        'snr_lora': snrLora,
        'snr_c0': snrC0,
        'snr_c1': snrC1,
        'snr_c3': snrC3,
      };

  String get hours {
    DateFormat dateFormat = DateFormat('yyyy-MM-dd HH:mm');
    int hour = dateFormat.parse(time).hour;
    String h = hour < 10 ? '0$hour' : hour.toString();
    return "$h:00:00-$h:59:59";
  }
}

class PickTaskResultPackageEntity implements Entity {
  int? id;
  int detectTaskId;
  DetectTaskEntity? detectTask;
  int? resultId;
  String time;
  String data;
  int channel;
  String modemType;
  int hz;

  PickTaskResultPackageEntity(this.detectTaskId, this.time, this.data, this.channel, this.modemType, this.hz);

  PickTaskResultPackageEntity.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        detectTaskId = json['detect_task_id'],
        detectTask = DetectTaskEntity.fromJson(json),
        resultId = json['result_id'],
        time = json['as_time'] ?? json['time'],
        data = json['data'],
        channel = json['channel'],
        modemType = json['modem_type'],
        hz = json['hz'];

  @override
  Map<String, dynamic> toJson() => {
        'id': id,
        'detect_task_id': detectTaskId,
        'result_id': resultId,
        'time': time,
        'data': data,
        'channel': channel,
        'modem_type': modemType,
        'hz': hz,
      };

  String get hours {
    DateFormat dateFormat = DateFormat('yyyy-MM-dd HH:mm:ss');
    int hour = dateFormat.parse(time).hour;
    String h = hour < 10 ? '0$hour' : hour.toString();
    return "$h:00:00-$h:59:59";
  }
}

class ChatEntity implements Entity {
  int? id;
  int senderId;
  String? senderName;
  int receiverId;
  String? receiverName;
  String content;
  int contentType;
  String time;

  ChatEntity(this.senderId, this.receiverId, this.content, this.contentType, this.time);

  ChatEntity.set({this.id, required this.senderId, this.senderName, required this.receiverId, this.receiverName, required this.content, required this.contentType, required this.time});

  ChatEntity.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        senderId = json['sender_id'],
        senderName = json['sender_name'],
        receiverId = json['receiver_id'],
        receiverName = json['receiver_name'],
        content = json['content'],
        contentType = json['content_type'],
        time = json['time'];

  @override
  Map<String, dynamic> toJson() => {
        'id': id,
        'sender_id': senderId,
        'receiver_id': receiverId,
        'content': content,
        'content_type': contentType,
        'time': time,
      };

  bool isLocal(int localId) => senderId == localId;

  bool get isVoice => contentType == 1;
}
